﻿/*
Copyright (c) 2011 Vratislav Cermak (vratacermak@gmail.com)
 
This file is part of TeachMe Project. See http://code.google.com/p/teach-me for more information.
 
TeachMe is an open source project. Using of TeachMe is free of charge.
It is distributed under GNU General Public License version 3 (GPLv3).
GPLv3 can be found at http://www.gnu.org/licenses/gpl.html.
 
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the license for more details.
*/

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Linq;
using System.Text.RegularExpressions;
using TeachMe.Application.Exceptions;
using HtmlAgilityPack;
using System.Text;

namespace TeachMe.Application.Translators
{
    public class Seznam : ITranslationProvider
    {
        private static List<Item<string, string>> _directions;

        private const string Mask = "http://slovnik.seznam.cz/{1}-{2}/word/?q={0}";

        public Seznam()
        {
            _directions = new List<Item<string, string>>();

            _directions.Add(new Item<string, string>("cz", "en"));
            _directions.Add(new Item<string, string>("en", "cz"));
            _directions.Add(new Item<string, string>("cz", "de"));
            _directions.Add(new Item<string, string>("de", "cz"));
            _directions.Add(new Item<string, string>("cz", "fr"));
            _directions.Add(new Item<string, string>("fr", "cz"));
            _directions.Add(new Item<string, string>("cz", "it"));
            _directions.Add(new Item<string, string>("it", "cz"));
            _directions.Add(new Item<string, string>("cz", "es"));
            _directions.Add(new Item<string, string>("es", "cz"));
            _directions.Add(new Item<string, string>("cz", "ru"));
            _directions.Add(new Item<string, string>("ru", "cz"));
            _directions.Add(new Item<string, string>("cz", "sk"));
            _directions.Add(new Item<string, string>("sk", "cz"));
        }

        public Dictionary<string, string[]> Translate(string word, string from, string to)
        {
            Dictionary<string, string[]> result = new Dictionary<string, string[]>();

            string query = String.Format(Mask, word, from, to);

            Logging.Debug(GetType(), "Translating '{0}' from '{1}' to '{2}' with: {3}", word, from, to, query);

            try
            {
                WebRequest request = WebRequest.Create(query);
                WebResponse response = request.GetResponse();

                using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                {
                    HtmlDocument document = new HtmlDocument();
                    document.Load(reader);

                    HtmlNodeCollection nodes = document.DocumentNode.SelectNodes("//div[@id=\"results\"]");
                    if (nodes.Count != 1)
                    {
                        return result;
                    }

                    HtmlNode resultNode = nodes.First();

                    HtmlNode node = resultNode.SelectSingleNode("div[@class=\"hgroup\"]/h3");
                    string sugo = node.InnerText.Trim();

                    node = resultNode.SelectSingleNode("div[@id=\"fastTrans\"]/div[@id=\"fastMeanings\"]");

                    List<string> translations = new List<string>();
                    StringBuilder builder = new StringBuilder();

                    foreach (HtmlNode child in node.ChildNodes)
                    {
                        if (String.Compare(child.Name, "br", true) == 0)
                        {
                            string[] split = builder.ToString().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                            translations.AddRange(split.Where(x => !translations.Contains(x)).Select(x => x.Trim()));
                            builder = new StringBuilder();
                        }
                        Add(child, builder);
                    }

                    result.Add(sugo, translations.ToArray());
                }
            }
            catch (Exception e)
            {
                Logging.Error(GetType(), e, "Translate query failed.");
            }

            Logging.Debug(GetType(), "Found '{0}' matches.", result.Count);

            return result;
        }

        private void Add(HtmlNode node, StringBuilder builder)
        {
            string text = Regex.Replace(node.InnerText.Trim(), @"s/<[a-zA-Z\/][^>]*>//g", " ").Trim();
            if (!String.IsNullOrEmpty(text))
            {
                if (builder.Length > 0)
                {
                    builder.Append(" ");
                }
                builder.Append(text);
            }
        }

        public string Caption
        {
            get { return "Seznam.cz"; }
        }

        public override string ToString()
        {
            return Caption;
        }

        public List<Item<string, string>> Directions
        {
            get { return _directions; }
        }
    }
}
